package com.merlin.security.browser;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import com.merlin.security.browser.authentication.MerlinAuthenticationFailureHandler;
import com.merlin.security.browser.authentication.MerlinAuthenticationSuccessHandler;
import com.merlin.security.core.properties.SecurityProperties;
import com.merlin.security.core.validate.code.ValidateCodeFilter;


/**
 * 浏览器安全配置
 * @author Administrator
 *
 */
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private SecurityProperties securityProperties;
	
	@Autowired
	private MerlinAuthenticationSuccessHandler merlinAuthenticationSuccessHandler;
	
	@Autowired
	private MerlinAuthenticationFailureHandler merlinAuthenticationFailureHandler;
	
	/**
	 * 数据源
	 */
	@Autowired
	private DataSource dataSource;
	
	@Autowired
	private UserDetailsService userDetailsService;
	
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
	/**
	 * 实现记住我 中的TokenRepository
	 * @return
	 */
	@Bean
	public PersistentTokenRepository persistentTokenRepository() {
		JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
		tokenRepository.setDataSource(dataSource);
		tokenRepository.setCreateTableOnStartup(true);//设置成true的话，系统在启动的时候自动创建表。
		return tokenRepository;
	}
	
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
		validateCodeFilter.setAuthenticationFailureHandler(merlinAuthenticationFailureHandler);
		validateCodeFilter.setSecurityProperties(securityProperties);//传入配置
		validateCodeFilter.afterPropertiesSet(); //调用初始化方法
		
		http
			.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class) //将验证码过滤器加在用户名密码过滤器之前
			.formLogin()
				.loginPage("/authentication/require") //自定义登录界面
				.loginProcessingUrl("/authentiaction/form") //表单登录请求的路径
				//.httpBasic()  //基于httpBasic认证
				.successHandler(merlinAuthenticationSuccessHandler) //添加成功处理器
				.failureHandler(merlinAuthenticationFailureHandler) //添加失败处理器
				.and()   
			//记住我配置
			.rememberMe()
				.tokenRepository(persistentTokenRepository())
				.tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())//过期使时间
				.userDetailsService(userDetailsService) //用户信息
				.and()
			.authorizeRequests() //认证请求    
			.antMatchers("/authentication/require",securityProperties.getBrowser().getLoginPage(),
					"/code/image").permitAll() //匹配merlin-signIn.html 不需要权限
			.anyRequest()        //所有请求
			.authenticated()    //需要认证
			.and()
			.csrf().disable(); //springsecurity 默认开启跨站请求防护的功能 ，先关闭
	}
}
